//=========================================================================
// Copyright (C) 2024 The C++ Component Model(COMO) Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//=========================================================================

#include "pmfunction.h"
#include "pminternal.h"

void *pmalign(void *md, const size_t alignment, const size_t size)
{
    void *result;
    unsigned long int adj;
    struct alignlist *ablist;
    struct mdesc *mdp = static_cast<struct mdesc *>(md);

    result = pmalloc(md, size + alignment - 1);
    if (result != nullptr) {
        adj = RESIDUAL(result, alignment);
        if (adj != 0) {
            for (ablist = mdp->aligned_blocks;  ablist != nullptr;
                                                        ablist = ablist->next) {
                if (nullptr == ablist->alignedaddr) {
                    break;
                }
            }
            if (nullptr == ablist) {
                ablist =
                    static_cast<alignlist *>(pmalloc(md, sizeof(struct alignlist)));
                if (nullptr == ablist) {
                    pmfree(md, result);
                    return (nullptr);
                }
                ablist->next = mdp->aligned_blocks;
                mdp->aligned_blocks = ablist;
            }
            ablist->unalignedaddr = result;
            ablist->alignedaddr = static_cast<char *>(result) + alignment - adj;
            result = ablist->alignedaddr;
        }
    }
    return (result);
}
